#include "warray/warray_blas.h"
#include "test.h"

#include <iostream>

#include "custom_type.h"
#include "helper.h"

typedef std::complex<float> cfloat;
typedef std::complex<double> cdouble;

typedef boost::mpl::list<int,float,double> scalar_types;
typedef boost::mpl::list<cfloat,cdouble> complex_types;
typedef boost::mpl::list<int,float,double,cfloat,cdouble> all_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( s_asum, T, scalar_types )
{
	T input[] = {1,-1,1,-1};
	BOOST_CHECK_EQUAL( warp::blas::asum(4,input,1), T(4) );
	BOOST_CHECK_EQUAL( warp::blas::asum(2,input,2), T(2) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_asum, T, complex_types )
{
	T input[] = {T(1,-1),T(-1,1),T(1,-1),T(-1,1)};
	BOOST_CHECK_EQUAL( warp::blas::asum(4,input,1), 8 );
	BOOST_CHECK_EQUAL( warp::blas::asum(2,input,2), 4 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_axpy, T, all_types )
{
	T input[] = {1,2,3,4};
	T x[] = {5,6,7,8};
	T y[] = {0,0,0,0};
	
	warp::blas::copy(4,input,1,y,1);
	BOOST_REQUIRE_EQUAL_COLLECTIONS(input,input+4,y,y+4);
	
	warp::blas::axpy(4,x,1,y,1,T(0));
	BOOST_CHECK_EQUAL_COLLECTIONS(input,input+4,y,y+4);
	
	{
		T result[] = {6,8,10,12};
		warp::blas::copy(4,input,1,y,1);
		warp::blas::axpy(4,x,1,y,1,T(1));
		BOOST_CHECK_EQUAL_COLLECTIONS(result,result+4,y,y+4);
	}
	
	{
		T result[] = {11,14,17,20};
		warp::blas::copy(4,input,1,y,1);
		warp::blas::axpy(4,x,1,y,1,T(2));
		BOOST_CHECK_EQUAL_COLLECTIONS(result,result+4,y,y+4);
	}
	
	{
		T result[] = {6,2,10,4};
		warp::blas::copy(4,input,1,y,1);
		warp::blas::axpy(2,x,2,y,2,T(1));
		BOOST_CHECK_EQUAL_COLLECTIONS(result,result+4,y,y+4);
	}
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_axpy, T, complex_types )
{
	T input[] = {T(1,2),T(3,4),T(5,6),T(7,8)};
	T x[] = {T(9,10),T(11,12),T(13,14),T(15,16)};;
	T y[] = {0,0,0,0};
	
	warp::blas::copy(4,input,1,y,1);
	BOOST_REQUIRE_EQUAL_COLLECTIONS(input,input+4,y,y+4);
	warp::blas::axpy(4,x,1,y,1,T(0));
	BOOST_CHECK_EQUAL_COLLECTIONS(input,input+4,y,y+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_copy, T, all_types )
{
	{
		T input[] = {1,2,3,4};
		T x[] = {0,0,0,0};
		warp::blas::copy(4,input,1,x,1);
		BOOST_CHECK_EQUAL_COLLECTIONS(input,input+4,x,x+4);
	}
	{
		T input[] = {1,2,3,4};
		T x[] = {0,0,0,0};
		T result[] = {1,0,3,0};
		warp::blas::copy(2,input,2,x,2);
		BOOST_CHECK_EQUAL_COLLECTIONS(result,result+4,x,x+4);
	}	
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_copy, T, complex_types )
{
	T input[] = {T(1,2),T(3,4),T(5,6),T(7,8)};
	T x[] = {0,0,0,0};
	warp::blas::copy(4,input,1,x,1);
	BOOST_CHECK_EQUAL_COLLECTIONS(input,input+4,x,x+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_dot, T, scalar_types )
{
	T x[4] = { 1,2,3,4 };
	T y[4] = { 5,6,7,8 };
	BOOST_CHECK_EQUAL( warp::blas::dot(4,x,1,y,1), T(70) );
	BOOST_CHECK_EQUAL( warp::blas::dot(2,x,2,y,2), T(26) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_dot, T, complex_types )
{
	T x[4] = { T(1,2),T(3,4),T(5,6),T(7,8) };
	T y[4] = { T(9,10),T(11,12),T(13,14),T(15,16) };
	BOOST_CHECK_EQUAL( warp::blas::dot(4,x,1,y,1), T(-68,488) );
	BOOST_CHECK_EQUAL( warp::blas::dot(2,x,2,y,2), T(-30,176) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_dotc, T, complex_types )
{
	T x[4] = { T(1,-2),T(3,-4),T(5,-6),T(7,-8) };
	T y[4] = { T(9,10),T(11,12),T(13,14),T(15,16) };
	BOOST_CHECK_EQUAL( warp::blas::dotc(4,x,1,y,1), T(-68,488) );
	BOOST_CHECK_EQUAL( warp::blas::dotc(2,x,2,y,2), T(-30,176) );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_nrm2, T, scalar_types )
{
	T x[4] = { 2, 4, 4, 0 };
	T y[4] = { 3, 6, 4, 6 };
	BOOST_CHECK_EQUAL( warp::blas::nrm2(4,x,1), 6 );
	BOOST_CHECK_EQUAL( warp::blas::nrm2(2,y,2), 5 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_nrm2, T, complex_types )
{
	T x[4] = { T(3,4), T(4,3), T(3,4), T(4,3) };
	T y[4] = { T(2,4), T(8,8), T(0,4), T(8,8) };
	BOOST_CHECK_EQUAL( warp::blas::nrm2(4,x,1), 10 );
	BOOST_CHECK_EQUAL( warp::blas::nrm2(2,y,2), 6 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_rot, T, scalar_types )
{
	T xi[3][4] = { {1,2,3,4}, {1,2,3,4}, {1,2,3,4} };
	T yi[3][4] = { {5,6,7,8}, {5,6,7,8}, {5,6,7,8} };
	T s = 2;
	T c = 3;
	T xo[3][4];
	T yo[3][4];
	for(int i=0;i<3;++i)
	{
		for(int j=0;j<4;++j)
		{
			xo[i][j] = c * xi[i][j] + s * yi[i][j];
			yo[i][j] = c * yi[i][j] - s * xi[i][j];
		}
	}
	xo[2][1] = xi[2][1];
	yo[2][1] = yi[2][1];
	xo[2][3] = xi[2][3];
	yo[2][3] = yi[2][3];
	
	warp::blas::rot(4,xi[0],1,yi[0],1,c,s);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi[0],xi[0]+4,xo[0],xo[0]+4);
	BOOST_CHECK_EQUAL_COLLECTIONS(yi[0],yi[0]+4,yo[0],yo[0]+4);
		
	warp::blas::rot(2,xi[2],2,yi[2],2,c,s);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi[2],xi[2]+4,xo[2],xo[2]+4);
	BOOST_CHECK_EQUAL_COLLECTIONS(yi[2],yi[2]+4,yo[2],yo[2]+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_scal, T, all_types )
{
	T xi[3][4] = { {1,2,3,4}, {1,2,3,4}, {1,2,3,4} };
	T xo[3][4] = { {2,4,6,8}, {2,4,6,8}, {2,2,6,4} };
	
	warp::blas::scal(4,T(2),xi[0],1);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi[0],xi[0]+4,xo[0],xo[0]+4);
		
	warp::blas::scal(2,T(2),xi[2],2);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi[2],xi[2]+4,xo[2],xo[2]+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_scal, T, complex_types )
{
	T xi[3][4] = { {T(1,2),T(3,4),T(5,6),T(7,8)}, {T(1,2),T(3,4),T(5,6),T(7,8)}, {T(1,2),T(3,4),T(5,6),T(7,8)} };
	T xo[3][4] = { {T(2,4),T(6,8),T(10,12),T(14,16)}, {T(2,4),T(6,8),T(10,12),T(14,16)}, {T(2,4),T(3,4),T(10,12),T(7,8)} };
	
	warp::blas::scal(4,T(2),xi[0],1);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi[0],xi[0]+4,xo[0],xo[0]+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_swap, T, all_types )
{
	T xi[] = {1,2,3,4};
	T yi[] = {5,6,7,8};
	T xo[] = {5,6,7,8};
	T yo[] = {1,2,3,4};

	warp::blas::swap(4,xi,1,yi,1);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi,xi+4,xo,xo+4);
	BOOST_CHECK_EQUAL_COLLECTIONS(yi,yi+4,yo,yo+4);
		
	warp::blas::swap(2,xi,2,yi,2);
	std::swap(xo[0],yo[0]); std::swap(xo[2],yo[2]);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi,xi+4,xo,xo+4);
	BOOST_CHECK_EQUAL_COLLECTIONS(yi,yi+4,yo,yo+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_swap, T, complex_types )
{
	T xi[4] = { T(1,2),T(3,4),T(5,6),T(7,8) };
	T yi[4] = { T(9,10),T(11,12),T(13,14),T(15,16) };
	T xo[4] = { T(9,10),T(11,12),T(13,14),T(15,16) };
	T yo[4] = { T(1,2),T(3,4),T(5,6),T(7,8) };
	
	warp::blas::swap(4,xi,1,yi,1);
	BOOST_CHECK_EQUAL_COLLECTIONS(xi,xi+4,xo,xo+4);
	BOOST_CHECK_EQUAL_COLLECTIONS(yi,yi+4,yo,yo+4);
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_amax, T, scalar_types )
{
	T x[4] = {-3, -2, 5, -6 };
	BOOST_CHECK_EQUAL( warp::blas::amax(4,x,1),    3 );
	BOOST_CHECK_EQUAL( warp::blas::amax(2,x,2),    1 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_amax, T, complex_types )
{
	T x[4] = {T(-2,1), T(-2,-1), T(-2,3), T(3,3) };
	BOOST_CHECK_EQUAL( warp::blas::amax(4,x,1),    3 );
	BOOST_CHECK_EQUAL( warp::blas::amax(2,x,2),    1 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_amin, T, scalar_types )
{
	T x[4] = {-3, -2, 5, -6 };
	BOOST_CHECK_EQUAL( warp::blas::amin(4,x,1),    1 );
	BOOST_CHECK_EQUAL( warp::blas::amin(2,x,2),    0 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_amin, T, complex_types )
{
	T x[4] = {T(-2,3), T(3,3), T(-2,-1), T(-2,1) };
	BOOST_CHECK_EQUAL( warp::blas::amin(4,x,1),    2 );
	BOOST_CHECK_EQUAL( warp::blas::amin(2,x,2),    1 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_gemv, T, all_types )
{
	T x[][3] = { 
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,9},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{3,2,1},
		{1,2,3},
		{1,2,3},
		{1,9,2},
		};
	T a[][9] = { 
		{1,0,0, 0,1,0, 0,0,1},
		{1,0,0, 0,1,0, 0,0,1},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,9, 4,5,9, 9,9,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{4,5,6, 9,9,9, 9,9,9},
		{4,9,9, 5,9,9, 6,9,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,9, 4,5,9, 9,9,9},
		};
	T y[][3] = { 
		{4,5,6},
		{4,5,6},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		{10,10,10},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		};
	T ans[][3] = { 
		{1,2,3},
		{4,5,6},
		{14,32,50},
		{5,14,-1},
		{28,64,100},
		{24,42,60},
		{32,-1,-1},
		{12,15,18},
		{30,36,42},
		{9,12,15},
		{5,-1,14},
		};
	
	int i=0;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(0), T(1), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;

	gemv( 2, 2, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(2), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(1), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 1, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 1, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 2, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 2, 2, a[i], 3, x[i], 2, y[i], 2, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_gemv, T, complex_types )
{
	T x[][3] = { 
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		};
	T a[][9] = { 
		{1,0,0, 0,1,0, 0,0,1},
		{1,0,0, 0,1,0, 0,0,1},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T y[][3] = { 
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		};
	T ans[][3] = { 
		{T(1,2),T(3,4),T(5,6)},
		{T(7,8),T(9,10),T(11,12)},
		{T(-21,88),T(-39,214),T(-57,340)},
		{T(-10,28),T(-22,88),T(11,12)},
		{T(-42,176),T(-78,428),T(-114,680)},
		{T(-14,96),T(-30,224),T(-46,352)},
		{T(-21,88),T(9,10),T(11,12)},
		{T(-3,4),T(-9,22),T(-15,40)},
		{T(-33,204),T(-39,246),T(-45,288)},
		{T(-14,56),T(-18,76),T(-22,96)},
		{T(-12,42),T(9,10),T(-24,126)},
		};
	
	int i=0;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(0), T(1), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;

	gemv( 2, 2, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(2), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(1), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 1, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 1, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 3, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 2, 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	gemv( 2, 2, a[i], 3, x[i], 2, y[i], 2, T(1), T(0), warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_ger, T, all_types )
{
	T x[][3] = {
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		};
	T y[][3] = {
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		};
	T a[][9] = { 
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,-1, 4,5,-1, -1,-1,-1},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		};
	T ans[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{5,7,9, 12,15,18, 19,23,27},
		{5,8,-1, 16,23,-1, -1,-1,-1},
		{9,12,15, 20,25,30, 31,38,45},
		{5,7,9, 4,5,6, 7,8,9},
		{5,2,3, 12,5,6, 19,8,9},
		};
	int i=0;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(0) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 2, 2, x[i], 2, y[i], 2, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(2) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 1, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 1, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_ger, T, complex_types )
{
	T x[][3] = {
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		};
	T y[][3] = {
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		};
	T a[][9] = { 
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T ans[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(-8,24),T(-8,32),T(-8,40), T(-4,60),T(-4,76),T(-4,92), T(0,96),T(0,120),T(0,144)},
		{T(-8,24),T(-10,38),T(5,6), T(-6,90),T(-8,136),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(-17,46),T(-19,60),T(-21,74), T(-15,112),T(-17,142),T(-19,172), T(-13,178),T(-15,224),T(-17,270)},
		{T(-8,24),T(-8,32),T(-8,40), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(-8,24),T(3,4),T(5,6), T(-4,60),T(9,10),T(11,12), T(0,96),T(15,16),T(17,18)},
		};
	int i=0;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(0) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 2, 2, x[i], 2, y[i], 2, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(2) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 1, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::ger( 3, 1, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_gerc, T, complex_types )
{
	T x[][3] = {
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		{T(1,2),T(3,4),T(5,6)},
		};
	T y[][3] = {
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		{T(7,8),T(9,10),T(11,12)},
		};
	T a[][9] = { 
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T ans[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(24,8),T(32,12),T(40,16), T(60,12),T(76,16),T(92,20), T(96,16),T(120,20),T(144,24)},
		{T(24,8),T(38,14),T(5,6), T(90,10),T(136,16),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(47,14),T(61,20),T(75,26), T(113,16),T(143,22),T(173,28), T(179,18),T(225,24),T(271,30)},
		{T(24,8),T(32,12),T(40,16), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(24,8),T(3,4),T(5,6), T(60,12),T(9,10),T(11,12), T(96,16),T(15,16),T(17,18)},
		};
	int i=0;
	
	warp::blas::gerc( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(0) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gerc( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gerc( 2, 2, x[i], 2, y[i], 2, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gerc( 3, 3, x[i], 1, y[i], 1, a[i], 3, T(2) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gerc( 1, 3, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gerc( 3, 1, x[i], 1, y[i], 1, a[i], 3, T(1) );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_symv, T, scalar_types )
{
	T x[][3] = { 
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,-1,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,-1,3},
		{1,2,3},
		{1,2,3},
		};
	T a[][9] = { 
		{1,0,0, 0,1,0, 0,0,1},
		{1,0,0, 0,1,0, 0,0,1},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,9, 4,5,9, 9,9,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,0,0, 0,1,0, 0,0,1},
		{1,0,0, 0,1,0, 0,0,1},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,9, 4,5,9, 9,9,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		};
	T y[][3] = { 
		{4,5,6},
		{4,5,6},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{-1,-1,-1},
		{-1,-1,-1},
		{-1,-1,-1},
		{4,5,6},
		};
	T ans[][3] = { 
		{1,2,3},
		{4,5,6},
		{14,30,42},
		{7,-1,17},
		{28,60,84},
		{18,35,48},
		{1,2,3},
		{4,5,6},
		{30,38,50},
		{13,-1,19},
		{60,76,100},
		{34,43,56},
		};
	
	int i=0;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(0), T(1), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;

	symv( 2, a[i], 3, x[i], 2, y[i], 2, T(1), T(0), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(2), T(0), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(1), warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
		
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(0), T(1), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(0), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;

	symv( 2, a[i], 3, x[i], 2, y[i], 2, T(1), T(0), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(2), T(0), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;
	
	symv( 3, a[i], 3, x[i], 1, y[i], 1, T(1), T(1), warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(y[i],y[i]+3,ans[i],ans[i]+3);
	++i;

}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_syr, T, scalar_types )
{
	T x[][3] = {
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		};
	T a[][9] = { 
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{0,0,0, 0,0,0, 0,0,0},
		{0,0,0, 0,0,0, 0,0,0},
		{1,2,3, 4,5,6, 7,8,9},
		{1,4,7, 2,5,8, 3,6,9},
		{0,0,0, 0,0,0, 0,0,0},
		{0,0,0, 0,0,0, 0,0,0},
		};
	T ans[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 0,4,6, 0,0,9},
		{1,0,0, 2,4,0, 3,6,9},
		{2,4,6, 4,9,12, 7,8,18},
		{2,4,7, 4,9,8, 6,12,18},
		{1,3,0, 0,9,0, 0,0,0},
		{1,0,0, 3,9,0, 0,0,0},
		};
	int i=0;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(0), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(0), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 3, x[i], 1, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 2, x[i], 2, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr( 2, x[i], 2, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_syr2, T, scalar_types )
{
	T x[][3] = {
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		{1,2,3},
		};
	T y[][3] = {
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		{4,5,6},
		};
	T a[][9] = { 
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{0,0,0, 0,0,0, 0,0,0},
		{0,0,0, 0,0,0, 0,0,0},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{0,0,0, 0,0,0, 0,0,0},
		{0,0,0, 0,0,0, 0,0,0},
		};
	T ans[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{8,13,18, 0,20,27, 0,0,36},
		{8,0,0, 13,20,0, 18,27,36},
		{9,15,21, 4,25,33, 7,8,45},
		{9,2,3, 17,25,6, 25,35,45},
		{8,18,0, 0,36,0, 0,0,0},
		{8,0,0, 18,36,0, 0,0,0},
		};
	int i=0;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(0), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(0), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 3, x[i], 1, y[i], 1, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 2, x[i], 2, y[i], 2, a[i], 3, T(1), warp::blas::upper_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2( 2, x[i], 2, y[i], 2, a[i], 3, T(1), warp::blas::lower_triangular );
	BOOST_CHECK_EQUAL_COLLECTIONS(a[i],a[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_gemm, T, all_types )
{
	T a[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		};
	T b[][9] = {
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		};
	T c[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		};
	T ans[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{84,90,96, 201,216,231, 318,342,366},
		{103,110,117, 223,239,255, 343,368,393},
		{29,31,33, 62,67,72, 95,103,111},
		{103,20,21, 22,23,24, 25,26,27},
		{174,186,198, 213,228,243, 252,270,288},
		{68,86,104, 167,212,257, 266,338,410},
		};
	int i=0;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(0), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 1, 1, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_gemm, T, complex_types )
{
	T a[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T b[][9] = {
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		};
	T c[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T ans[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(-87,582),T(-93,624),T(-99,666), T(-105,1500),T(-111,1614),T(-117,1728), T(-123,2418),T(-129,2604),T(-135,2790)},
		{T(-86,584),T(-90,628),T(-94,672), T(-98,1508),T(-102,1624),T(-106,1740), T(-110,2432),T(-114,2620),T(-118,2808)},
		{T(-21,58),T(-23,64),T(-25,70), T(-27,292),T(-29,322),T(-31,352), T(-33,526),T(-35,580),T(-37,634)},
		{T(-87,582),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		{T(-99,1290),T(-105,1380),T(-111,1470), T(-105,1596),T(-111,1710),T(-117,1824), T(-111,1902),T(-117,2040),T(-123,2178)},
		{T(-75,466),T(-93,592),T(-111,718), T(-93,1240),T(-111,1582),T(-129,1924), T(-111,2014),T(-129,2572),T(-147,3130)},
		};
	int i=0;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(0), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 1, 1, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::dont_transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::gemm( 3, 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::transpose);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_syrk, T, all_types )
{
	T a[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		};
	T c[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		};
	T ans[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{14,32,50, 22,77,122, 25,26,194},
		{14,20,21, 32,77,24, 50,122,194},
		{33,52,71, 22,100,146, 25,26,221},
		{33,20,21, 54,100,24, 75,148,221},
		{1,4,7, 22,16,28, 25,26,49},
		{1,20,21, 4,16,24, 7,28,49},
		{1,2,3, 22,4,6, 25,26,9},
		{1,20,21, 2,4,24, 3,6,9},
		};
	int i = 0;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(0), T(1), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 1, a[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 1, a[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 1, a[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syrk( 3, 1, a[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_syrk, T, complex_types )
{
	// Most tests are handled by the scalar version, we do an additional one
	// to verify the complex arithmatic
	T a[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T c[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T ans[][9] = {
		{T(-21,88),T(-39,214),T(-57,340), T(7,8),T(-57,556),T(-75,898), T(13,14),T(15,16),T(-93,1456)},
		};
	int i = 0;
	
	warp::blas::syrk( 3, 3, a[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( s_syr2k, T, all_types )
{
	T a[][9] = {
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		{1,2,3, 4,5,6, 7,8,9},
		};
	T b[][9] = {
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		{10,11,12, 13,14,15, 16,17,18},
		};
	T c[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		{19,20,21, 22,23,24, 25,26,27},
		};
	T ans[][9] = {
		{19,20,21, 22,23,24, 25,26,27},
		{136,253,370, 22,424,595, 25,26,820},
		{136,20,21, 253,424,24, 370,595,820},
		{155,273,391, 22,447,619, 25,26,847},
		{155,20,21, 275,447,24, 395,621,847},
		{20,53,86, 22,104,155, 25,26,224},
		{20,20,21, 53,104,24, 86,155,224},
		{20,31,42, 22,44,57, 25,26,72},
		{20,20,21, 31,44,24, 42,57,72},
		};
	int i=0;

	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(0), T(1), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(1), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
	
	warp::blas::syr2k( 3, 1, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::transpose, warp::blas::lower_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}

BOOST_AUTO_TEST_CASE_TEMPLATE( c_syr2k, T, complex_types )
{
	// Most tests are handled by the scalar version, we do an additional one
	// to verify the complex arithmatic
	T a[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T b[][9] = {
		{T(19,20),T(21,22),T(23,24), T(25,26),T(27,28),T(29,30), T(31,32),T(33,34),T(35,36)},
		};
	T c[][9] = {
		{T(1,2),T(3,4),T(5,6), T(7,8),T(9,10),T(11,12), T(13,14),T(15,16),T(17,18)},
		};
	T ans[][9] = {
		{T(-150,932),T(-186,1832),T(-222,2732), T(7,8),T(-222,3164),T(-258,4496), T(13,14),T(15,16),T(-294,6260)},
		};
	int i = 0;
	
	warp::blas::syr2k( 3, 3, a[i], 3, b[i], 3, c[i], 3, T(1), T(0), warp::blas::dont_transpose, warp::blas::upper_triangular);
	BOOST_CHECK_EQUAL_COLLECTIONS(c[i],c[i]+9,ans[i],ans[i]+9);
	++i;
}



